package ide.ccf.ccproject.wizards.pages;

import ide.ccf.ccproject.common.Utils;
import ide.ccf.ccproject.common.WizardUtils;
import ide.ccf.ccproject.templateengine.SwitchGuiProjectData;
import ide.ccf.ccproject.translate.Message;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Locale;

import org.eclipse.cdt.core.CConventions;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.ContainerSelectionDialog;


/**
 * 新建UI文件向导页面
 *
 */
public class UiFileWizardPage extends WizardPage implements KeyListener 
{
	private boolean uichanged = false;
	
	private Group uigroup;
	private Text containerText;
	private Text classText;
	private Text uiFileName;
	private Text headerFileName;
	private Text sourceFileName;
	private Combo uiType;
	private Label uiTypeLable;
	private Button filesLowerCase;
	private ISelection selection;
	
	/**
	 * 构造器
	 * @param selection
	 */
	public UiFileWizardPage(ISelection selection) 
	{
		super("");
		
		this.selection = selection;
		setTitle(Message.UiFileWizardPage_0);
		setDescription(Message.UiFileWizardPage_1);
	}

	/**
	 * 获取UI文件名
	 * @return
	 */
	private String getUiFileName() {
		return uiFileName.getText();
	}
	
	/**
	 * 获取基本UI文件名
	 * @return
	 */
	private String getUiFileNameBase() 
	{
		return Utils.getFileName(new Path(getUiFileName()), true);
	}
	
	/**
	 * 获取头文件名
	 * @return
	 */
	private String getHeaderFileName() 
	{
		return headerFileName.getText();
	}
	
	/**
	 * 获取基本头文件名
	 * @return
	 */
	private String getHeaderFileNameBase() 
	{
		return Utils.getFileName(new Path(getHeaderFileName()), true);
	}
	
	/**
	 * 获取相对头文件名
	 * @return
	 */
	private String getRelativeHeaderFileName() 
	{
		return Utils.makeRelative(new Path(getContainerName() + "/" + getHeaderFileName()), new Path(getContainerName() + "/" + getSourceFileName())).toString();
	}
	
	/**
	 * 获取源文件名
	 * @return
	 */
	private String getSourceFileName() 
	{
		return sourceFileName.getText();
	}
	
	/**
	 * 获取所有文件名
	 * @return
	 */
	private String[] getFileNames() 
	{
		return new String[] {getUiFileName(), getHeaderFileName(), getSourceFileName()};
	}

	/**
	 * 获取所有文件所在路径
	 * @return
	 */
	private String[] getFileLocations() 
	{
		return new String[] {getContainerName(), getContainerName(), getContainerName()};
	}
	
	/**
	 * 获取父类名
	 * @return
	 */
	private String getUISuperClass() 
	{
		//return uiType.getText();
		
		switch (uiType.getSelectionIndex())
		{
			case 0:
				return "QWidget";
				
			case 1:
				return "QMainWindow";
				
			case 2:
				return "QDialog";
				
			default:
				return "";
		}
	}

	/**
	 * 创建文件
	 * @param monitor
	 * @throws CoreException
	 */
	@SuppressWarnings("unchecked")
	public void createFiles(IProgressMonitor monitor) throws CoreException 
	{

		String baseClass = getUISuperClass();
		String className = getClassName();
		@SuppressWarnings("rawtypes")
		HashMap replaceMap = new HashMap();
		
		replaceMap.put("%PRE_DEF%", getHeaderFileNameBase().toUpperCase(Locale.US).replace('.', '_') + "_H");
		replaceMap.put("%UI_CLASS%", baseClass);
		replaceMap.put("%CLASS%", className);
		replaceMap.put("%UI_HDR%", "ui_" + getUiFileNameBase() + ".h");
		replaceMap.put("%INCLUDE%", getRelativeHeaderFileName());

		String[] templates = {baseClass + ".ui", "gui.h", "gui.cpp"};
		String[] fileNames = getFileNames();
		String[] locations = getFileLocations();
		String filePath = UiFileWizardPage.class.getProtectionDomain().getCodeSource().getLocation().toString();

		//得到{file:/home/chengzhibin/git/IDECCfEclipse/CCFEclipseIntergration/ide.ccf.ccproject/}数据，
		//需要进行截取转化
		String fPath[] = filePath.split(":");
		for (int i = 0; i < templates.length; i++) 
		{
			InputStream template = null;
			try {
				template = new FileInputStream(fPath[1] +	"/templates/GuiProject/Gui/" + templates[i]);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
	
			IFile file = WizardUtils.createFile(new Path(locations[i] + "/" + fileNames[i]), monitor);
			String source = "";
			
			if (template != null) 
				source = WizardUtils.patchTemplateFile(template, replaceMap);
			
			file.create(new ByteArrayInputStream(source.getBytes()), true, monitor);
		}
	}

	/**
	 * 界面显示控制
	 */
	public void createControl(Composite parent) 
	{
		Composite mainComposite = new Composite(parent, SWT.NONE);

		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		mainComposite.setLayout(layout);

		Composite container = new Composite(mainComposite, SWT.NONE);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		container.setLayoutData(gd);
		layout = new GridLayout();
		layout.numColumns = 3;
		layout.verticalSpacing = 9;
		container.setLayout(layout);
		
		Label label = new Label(container, SWT.NULL);
		label.setText(Message.UiFileWizardPage_10);

		containerText = new Text(container, SWT.BORDER | SWT.SINGLE);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		containerText.setLayoutData(gd);
		containerText.addModifyListener(new ModifyListener() 
		{
			public void modifyText(ModifyEvent e) 
			{
				dialogChanged();
			}
		});

		Button button = new Button(container, SWT.PUSH);
		button.setText(Message.UiFileWizardPage_11);
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				handleBrowse();
			}
		});

		label = new Label(container, SWT.NULL);
		label.setText(Message.FilesWizard_4);

		classText = new Text(container, SWT.BORDER | SWT.SINGLE);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		classText.setLayoutData(gd);
		classText.addModifyListener(new ModifyListener() 
		{
			public void modifyText(ModifyEvent e) 
			{
				syncFileNameBase();
				dialogChanged();
			}
		});

		label = new Label(container, SWT.NULL);
		
		uigroup = new Group(mainComposite, SWT.CHECK);
		uigroup.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
		uigroup.setText(Message.UiFileWizardPage_12);

		layout = new GridLayout();
		layout.numColumns = 2;
		uigroup.setLayout(layout);

		addFileNameLabel(Message.FilesWizard_7);
		uiFileName = addFileNameEditor();
		addFileNameLabel(Message.FilesWizard_6);
		headerFileName = addFileNameEditor();
		addFileNameLabel(Message.FilesWizard_5);
		sourceFileName = addFileNameEditor();

		uiTypeLable = new Label(uigroup, SWT.PUSH);
		uiTypeLable.setText(Message.FilesWizard_8);

		uiType = new Combo(uigroup, SWT.READ_ONLY);
		uiType.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
		uiType.setItems(new String[] { Message.FilesWizard_9, Message.FilesWizard_10, Message.FilesWizard_11 });
		uiType.select(0);
		
		filesLowerCase = new Button(uigroup, SWT.CHECK);
		filesLowerCase.setText(Message.UiFileWizardPage_2);
		filesLowerCase.setSelection(true);
		GridData data = new GridData();
		data.horizontalSpan = 2;
		filesLowerCase.setLayoutData(data);
		filesLowerCase.addSelectionListener(new SelectionListener() 
		{
			public void widgetDefaultSelected(SelectionEvent e) 
			{
				
			}
			
			public void widgetSelected(SelectionEvent e) 
			{
				syncFileNameBase();
			}
		});

		initialize();
		dialogChanged();
		setControl(mainComposite);
		setPageComplete(true);
	}

	/**
	 * 添加文件名Label
	 * @param text
	 * @return
	 */
	private Label addFileNameLabel(String text) 
	{
		Label label = new Label(uigroup, SWT.PUSH);
		label.setText(text);
		return label;
	}

	/**
	 * 添加文件名Edit
	 * @return
	 */
	private Text addFileNameEditor() 
	{
		Text editor = new Text(uigroup, SWT.BORDER | SWT.SINGLE);
		editor.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
		editor.addKeyListener(this);
		editor.addModifyListener(new ModifyListener() 
		{
			public void modifyText(ModifyEvent e) 
			{
				dialogChanged();
			}
		});
		return editor;
	}
	
	/**
	 * 按键
	 */
	public void keyPressed(KeyEvent e) 
	{

	}

	/**
	 * 释放按键
	 */
	public void keyReleased(KeyEvent e) 
	{
		uichanged = true;
		dialogChanged();
	}

	/**
	 * 同步文件基本名称
	 */
	private void syncFileNameBase() 
	{
		if (!uichanged) 
		{
			String className = getClassName();
			
			if (className.length() == 0) 
			{
				uiFileName.setText("");
				headerFileName.setText("");
				sourceFileName.setText("");
			} 
			else 
			{
				uiFileName.setText("./" + getFileBaseFromClassName() + ".ui");
				headerFileName.setText("./" + getFileBaseFromClassName() + ".h");
				sourceFileName.setText("./" + getFileBaseFromClassName() + ".cpp");
			}
			dialogChanged();
		}
	}

	/**
	 * 获取容器名称
	 * @return
	 */
	private String getContainerName() 
	{
		return containerText.getText();
	}
	
	/**
	 * 获取类名
	 * @return
	 */
	private String getClassName() 
	{
		return classText.getText();
	}

	/**
	 * 对话框变化事件处理
	 */
	private void dialogChanged() 
	{
		IResource container = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(getContainerName()));

		if (getContainerName().length() == 0) 
		{
			updateStatus(Message.ResourceWizardPage_4);
			return;
		}
		
		if (container == null || (container.getType() & (IResource.PROJECT | IResource.FOLDER)) == 0) 
		{
			updateStatus(Message.ResourceWizardPage_5);
			return;
		}
		
		if (!container.isAccessible()) 
		{
			updateStatus(Message.ResourceWizardPage_6);
			return;
		}
		
		if (getClassName().length() == 0) 
		{
			updateStatus(Message.UiFileWizardPage_3);
			return;
		}
		
		if (!isValidClassName()) 
		{
			return;
		}
		
		if (getUiFileName().length() == 0) 
		{
			updateStatus(Message.UiFileWizardPage_4);
			return;
		}
		
		if (getHeaderFileName().length() == 0) 
		{
			updateStatus(Message.UiFileWizardPage_5);
			return;
		}
		
		if (getSourceFileName().length() == 0) 
		{
			updateStatus(Message.UiFileWizardPage_6);
			return;
		}
		
		if (!getUiFileName().substring(getUiFileName().length()-3).equalsIgnoreCase(".ui")) 
		{
			updateStatus(Message.UiFileWizardPage_7);
			return;
		}
		
		String[] fileNames = getFileNames();
		String[] locations = getFileLocations();
		
		for (int i = 0; i < fileNames.length; i++) 
		{
			String name = locations[i] + "/" + fileNames[i];
			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); 
			
			if (root.findMember(name) != null) 
			{
				updateStatus("File" + name + "already exists");
				return;
			}
			
			IPath path = new Path(name);
			
			if (path.hasTrailingSeparator() || root.getFile(new Path(name)) == null) 
			{
				updateStatus(Message.UiFileWizardPage_8 + name + "'");
				return;
			}
		}
		updateStatus(null);
	}

	/**
	 * 检查类名合法性
	 * @return
	 */
	private boolean isValidClassName() 
	{
		final String invalidClassname =Message.UiFileWizardPage_9;
		IStatus val = CConventions.validateClassName(getClassName());
		
		if (val.getSeverity() == IStatus.ERROR) 
		{
			updateStatus(invalidClassname + val.getMessage());
			return false;
		} 
		else if (val.getSeverity() == IStatus.WARNING) 
		{
			setMessage(invalidClassname + val.getMessage(), WARNING);
		} 
		else 
		{
			setMessage(null);
		}
		setPageComplete(true);
		return true;
	}
	
	/**
	 * 根据类名获取文件基本名称
	 * @return
	 */
	private String getFileBaseFromClassName() 
	{
		String fileBase = getClassName();
		
		if (filesLowerCase.getSelection())
			fileBase = fileBase.toLowerCase(Locale.US);
		
		return fileBase;
	}
	
	/**
	 * 更新状态
	 * @param message
	 */
	private void updateStatus(String message) 
	{
		setErrorMessage(message);
		setPageComplete(message == null);
	}
	
	/**
	 * 浏览按钮事件处理
	 * 使用标准容器选择对话框选择源文件夹字段值
	 */
	private void handleBrowse() 
	{
		ContainerSelectionDialog dialog = new ContainerSelectionDialog(getShell(), ResourcesPlugin.getWorkspace().getRoot(), false, "选择源文件夹");
		
		if (dialog.open() == ContainerSelectionDialog.OK) 
		{
			Object[] result = dialog.getResult();
			
			if (result.length == 1) 
			{
				containerText.setText(((Path) result[0]).makeRelative().toString());
			}
		}
	}

	/**
	 * 初始化
	 */
	private void initialize() 
	{
		if (selection != null && selection.isEmpty() == false && selection instanceof IStructuredSelection) 
		{
			IStructuredSelection ssel = (IStructuredSelection) selection;
			
			if (ssel.size() > 1)
				return;
			
			Object obj = ssel.getFirstElement();
			
			if (!(obj instanceof IResource) && (obj instanceof IAdaptable))
				obj = ((IAdaptable)obj).getAdapter(IResource.class);
			
			if (obj instanceof IResource) 
			{
				IContainer container;
				
				if (obj instanceof IContainer)
					container = (IContainer) obj;
				else
					container = ((IResource) obj).getParent();
				
				containerText.setText(container.getFullPath().makeRelative().toString());
			}
		}
		classText.setFocus();
	}
}